package main

import (
	"context"
	"demo/services"
	"fmt"
	"google.golang.org/grpc"
	"io"
	"log"
	"time"
)

func main()  {
	conn, err := grpc.Dial("127.0.0.1:8081", grpc.WithInsecure())
	if err != nil{
		log.Fatal(err)
	}
	defer conn.Close()

	prodClient := services.NewProdServiceClient(conn)
	orderClient := services.NewOrderServicesClient(conn)

	ctx := context.Context(context.Background())
	// 返回单个值
	//prodRes, err := prodClient.GetProdStock(ctx, &services.ProdRequest{
	//	ProId: 12,
	//})
	//if err != nil {
	//	log.Fatal(err)
	//}
	//
	//fmt.Println(prodRes.ProdStock)

	// 返回多个值
	//response, err := prodClient.GetProdStocks(ctx, &services.QuerySize{Size: 20})
	//if err != nil{
	//	log.Fatal(err)
	//}
	//fmt.Println(response)

	// 枚举
	//prodRes, err := prodClient.GetProdStock(ctx, &services.ProdRequest{
	//	ProId: 12,
	//	ProdArea: 2,
	//})

	// 文件引入
	prodRes, err := prodClient.GetProdInfo(ctx, &services.ProdRequest{
		ProId: 12,
		ProdArea: 2,
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(prodRes)
	//
	//t := timestamp.Timestamp{Seconds: time.Now().Unix()}
	orderDetails := []*services.OrderDetail{
		&services.OrderDetail{DetailId: 102,OrderOn: "20210711", ProdId: 12,ProdPrice: 30.2,ProdNum: 20},
		&services.OrderDetail{DetailId: 103,OrderOn: "20210711", ProdId: 12,ProdPrice: 30.2,ProdNum: 20},
		&services.OrderDetail{DetailId: 104,OrderOn: "20210711", ProdId: 12,ProdPrice: 30.2,ProdNum: 20},
	}
	orderRes, err := orderClient.NewOrder(ctx, &services.OrderRequest{
		OrderMain: &services.OrderMain{
			OrderId: 12,
			OrderNo: "20210711",
			OrderMoney: 12.5,
			//OrderTime: &t,
			OrderDetail: orderDetails,
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(orderRes)


	// 流式发送数据到服务端(客户端流)
	//sendGoodsByTotalPrice(prodClient)

	// 发送商品所在区， 获取当前区的所有商品(服务端流)
	//sendAreaByGoods(prodClient)

	// 发送商品所在区(双向流)
	sendAreasByGoods(prodClient)

}

func sendGoodsByTotalPrice(prodClient services.ProdServiceClient)  {
	stream, err := prodClient.GetProdGoods(context.Background())
	if err != nil{
		log.Fatal(err)
	}

	goods := []*services.ProdModel{
		&services.ProdModel{ProdId: 101, ProdName: "测试商品1号", ProdPrice: 10.2},
		&services.ProdModel{ProdId: 102, ProdName: "测试商品2号", ProdPrice: 10.2},
		&services.ProdModel{ProdId: 103, ProdName: "测试商品3号", ProdPrice: 10.2},
		&services.ProdModel{ProdId: 104, ProdName: "测试商品4号", ProdPrice: 10.2},
	}

	// 循环发送数据
	for _, good := range goods{
		if err := stream.Send(good); err != nil{
			log.Fatal("发送数据错误", err)
		}
		time.Sleep(time.Second)
	}

	// 服务器端返回
	reply, err := stream.CloseAndRecv()
	if err != nil{
		log.Fatal("服务器端返回 err=", err)
	}

	log.Println(reply)
}

func sendAreaByGoods(prodClient services.ProdServiceClient){
	rect := &services.ProdRequestArea{
		ProdArea: services.ProdAreas_C,
	}
	stream, err := prodClient.GetProdAreasGoods(context.Background(), rect)

	if err != nil{
		log.Fatal("接收商品流错误 err=", err)
	}

	for {
		good, err := stream.Recv()
		if err == io.EOF{ // 接收结束
			break
		}
		if err != nil{
			log.Fatal("sendAreaByGoods err=", err)
		}
		fmt.Println(good)
	}
}

func sendAreasByGoods(prodClient services.ProdServiceClient){
	stream, err := prodClient.GetProdAreaListGoods(context.Background())
	if err != nil{
		log.Fatal("连接错误 err=", err)
	}
	waitc := make(chan struct{})
	go func() {
		for {
			in, err := stream.Recv()
			if err == io.EOF {
				// read done.
				close(waitc)
				return
			}
			if err != nil {
				log.Fatalf("Failed to receive a good : %v", err)
			}
			log.Printf("商品id = %v 商品名称 = %v 商品价格 = %v ", in.ProdId, in.ProdName, in.ProdPrice)
		}
	}()

	areas := []*services.ProdRequestArea{
		&services.ProdRequestArea{ProdArea: services.ProdAreas_A},
		&services.ProdRequestArea{ProdArea: services.ProdAreas_B},
		&services.ProdRequestArea{ProdArea: services.ProdAreas_C},
	}

	for _, area := range areas {
		if err := stream.Send(area); err != nil {
			log.Fatalf("Failed to send a area: %v", err)
		}
		time.Sleep(time.Second)
	}
	err = stream.CloseSend()
	if err != nil{log.Println("close send err =", err)}
	<-waitc
}